﻿/*-----------------------------------------------
// File: BCDefendState.cs 
// Description: 渲染曾，英雄对象防守状态，当轮对敌方阵营行动时，我方阵营的英雄对象会进入防御状态。 
// Author: Shaobing	492057342@qq.com
-----------------------------------------------*/
using UnityEngine;
using System.Collections;

namespace Battle.View
{
    public class BCDefendState : Fsm.FsmStateMonoBase<ActorState>
    {
        public DefendState defendState;

        private BattleCharacter owner;

        public IdleState idleState;

        public float totalFallTime = 1f;
        public float fallTimer = 0;
        //public float hitAgainTimer = 0;


        //public FallState fallState;

        //TODO动画时长问题需要处理
        //private float floatUpTime = 1;
        //private float floatTimer = 0;

        #region Flying 处理

        public float ACC_SPEED_UP = -8f;
        public const float ACC_SPEED_DOWN = -5f;
        public float totalFlyTime = 1f;


        //h=   -1/2   *   ACC_SPEED_UP    *   (flyTime-splitTime)^2    +   maxHeight
        //h=   -1/2   *   ACC_SPEED_DOWN  *   (flyTime-splitTime)^2    +   maxHeight

        private float splitTime = 0;
        private float maxHeight = 0;


        private float flyTime = 0;

        //public float behitTimer = 0;

        private void UpdatePosition()
        {
            if (owner.transform.localPosition.y > 0)
            {
                var p = owner.transform.localPosition;
                p.y += ACC_SPEED_DOWN * Time.deltaTime;
                p.y = Mathf.Max(0, p.y);
                owner.transform.localPosition = p;
            }
        }

        private void UpdateFloatPosition()
        {
            flyTime += Time.deltaTime;

            Vector3 p = owner.transform.localPosition;
            p.y = GetHeight(Mathf.Max(0f, flyTime));
            owner.transform.localPosition = p;
        }

        public float GetHeight(float time)
        {
            if (time < splitTime)
            {
                return 0.5f * ACC_SPEED_UP * (time - splitTime) * (time - splitTime) + maxHeight;
            }
            else
            {
                return 0.5f * ACC_SPEED_DOWN * (time - splitTime) * (time - splitTime) + maxHeight;
            }
        }


        #endregion Flying 处理

        public BCDefendState(ActorState state, BattleCharacter ctrl) : base(state, ctrl)
        {
            owner = ctrl;
        }

        public override void Enter()
        {
            owner.transform.SetParent(BattleViewCtrl.GetInstance().transform);
            owner.transform.localPosition = owner.GetStandPosition();
            owner.transform.localEulerAngles = owner.GetStandEulerAngle();
            owner.transform.localScale = Vector3.one;
            owner.PlayStand();
            //floatUpTime = owner.anim.anim[AniName.FLOAT_FLY].length;
            defendState = DefendState.IDLE;
            idleState = IdleState.NORMAL;
            flyTime = 0;

        }

        public override void Leave()
        {
            var p = owner.transform.localPosition;
            p.y = 0;
            owner.transform.localPosition = p;
        }

        public void Behit(/*float hitTime = 0*/)
        {
            switch (defendState)
            {
                case DefendState.IDLE:
                    //behitTimer = hitTime;
                    if (idleState == IdleState.NORMAL)
                    {
                        owner.anim.CrossFade(AniName.BEHIT, WrapMode.Clamp, true);
                    }
                    break;
                case DefendState.FLOAT:
                    owner.anim.CrossFade(AniName.FLOAT_FLY, WrapMode.Clamp, true);
                    break;
                case DefendState.FALL:
                    owner.anim.CrossFade(AniName.FALL_HIT, WrapMode.Clamp, true);
                    break;
            }
        }

        public void HitFly(bool force,double surplusTime)
        {
            totalFlyTime = (float)surplusTime;
            if (force)
            {
                if (defendState == DefendState.FLOAT)
                {
                    ACC_SPEED_UP = -2f;
                }
                else
                {

                    ACC_SPEED_UP = -8f;
                }

            }
            else
            {
                if (defendState == DefendState.FLOAT)
                    ACC_SPEED_UP = -1.2f;
            }
            if (owner.anim.IsPlaying(AniName.FLOAT_FLY))
            {
                owner.anim.anim[AniName.FLOAT_FLY].time = 5f / 30f;
            }
            else
            {
                owner.anim.CrossFade(AniName.FLOAT_FLY, WrapMode.Clamp, true, 0.1f);
            }
            defendState = DefendState.FLOAT;

            float height = GetHeight(flyTime);
            // height   == -1/2 * ACC_SPEED_UP      * splitTime^2                   + maxHeight ( 1 )
            // 0        == -1/2 * ACC_SPEED_DOWN    * (TOTAL_FLY_TIME-splitTime)^2  + maxHeight ( 2 )
            //( 2 ) - ( 1 ) 
            //< = > 
            //      ((-1/2 * ACC_SPEED_UP)-(-1/2 * ACC_SPEED_DOWN))   * splitTime^2
            //+     2 * (-1/2 * ACC_SPEED_DOWN)                     * splitTime     *   TOTAL_FLY_TIME
            //-     (-1/2 * ACC_SPEED_DOWN)                         * TOTAL_FLY_TIME^2 
            //-     height
            //==    0
            float a = ((0.5f * ACC_SPEED_UP) - (0.5f * ACC_SPEED_DOWN));
            float b = 2 * (0.5f * ACC_SPEED_DOWN) * totalFlyTime;
            float c = -(0.5f * ACC_SPEED_DOWN) * totalFlyTime * totalFlyTime - height;

            if (a != 0)//ACC_SPEED_UP!=ACC_SPEED_DOWN
            {
                float delta = b * b - 4 * a * c;
                if (delta >= 0)
                {
                    splitTime = (-b - Mathf.Sqrt(delta)) / (2 * a);
                }
                else
                {
                    Debug.LogError("Error In Calculate Height Curve");
                }
            }
            else
            {
                splitTime = ((0.5f * ACC_SPEED_UP) * totalFlyTime * totalFlyTime + height) / (2 * (0.5f * ACC_SPEED_UP) * totalFlyTime);
            }

            maxHeight = height - (0.5f * ACC_SPEED_UP) * splitTime * splitTime;

            flyTime = 0.0f;

        }


        public void HitFall(bool force, double surplusTime)
        {
            totalFallTime = (float)surplusTime;
            fallTimer = 0;
            switch (defendState)
            {
                case DefendState.IDLE:
                case DefendState.FLOAT:
                    defendState = DefendState.FALL;
                    //Debug.Log("Fall begin time " + Time.time);
                    owner.anim.CrossFade(AniName.FALL_DOWN, WrapMode.Once, false, 0.1f);
                    break;
                case DefendState.FALL:
                    owner.anim.CrossFade(AniName.FALL_DOWN, WrapMode.Once, true);
                    break;
            }
        }

        public override void Update()
        {
            switch (defendState)
            {
                case DefendState.IDLE:
                    UpdatePosition();
                    if (owner.anim.IsPlaying(AniName.BEHIT) || owner.anim.IsPlaying(AniName.FALL_GET_UP) /*|| owner.anim.IsPlaying(AniName.FLOAT_DOWN)*/)
                    {
                        break;
                    }
                    if (idleState == IdleState.NORMAL)
                    {
                        //if (behitTimer <= 0)
                        //{
                        if (!owner.anim.IsPlaying(AniName.IDLE_FIGHT))
                        {
                            if (owner.isWillDead)
                            {
                                owner.SwitchState(ActorState.Dead);
                                return;
                            }
                            owner.PlayStand();
                            //owner.anim.CrossFade(AniName.IDLE_FIGHT, WrapMode.Loop);
                        }
                        else
                        {
                            if (owner.isWillDead)
                            {
                                owner.SwitchState(ActorState.Dead);
                                return;
                            }
                        }
                        //}
                        //behitTimer -= Time.deltaTime;
                    }
                    else
                    {
                        if (owner.isWillDead)
                        {
                            owner.SwitchState(ActorState.Dead);
                            return;
                        }
                        idleState = IdleState.NORMAL;
                        owner.anim.CrossFade(AniName.FALL_GET_UP, WrapMode.Once);
                        owner.transform.localPosition = owner.GetStandPosition();
                    }
                    break;
                case DefendState.FLOAT:
                    if (flyTime >= totalFlyTime)
                    {
                        if (owner.isWillDead) {
                            owner.SwitchState(ActorState.Dead);
                            return;
                        }
                        defendState = DefendState.IDLE;
                        owner.anim.CrossFade(AniName.FALL_GET_UP, WrapMode.Once);
                        owner.transform.localPosition = owner.GetStandPosition();
                        flyTime = 0f;
                        break;
                    }
                    UpdateFloatPosition();
                    break;
                case DefendState.FALL:
                    UpdatePosition();
                    fallTimer += Time.deltaTime;
                    if (!owner.anim.isPlaying)
                    {
                        if (owner.isWillDead)
                        {
                            owner.SwitchState(ActorState.Dead);
                            return;
                        }
                        if (fallTimer >= totalFallTime)
                        {
                            defendState = DefendState.IDLE;
                            idleState = IdleState.NORMAL;
                            owner.anim.CrossFade(AniName.FALL_GET_UP, WrapMode.Once);
                            owner.transform.localPosition = owner.GetStandPosition();
                        }
                    }
                    break;
            }
            if (defendState != DefendState.FLOAT)
            {
                flyTime = maxHeight = splitTime = 0f;
            }
        }

    }

}